﻿using System;
using System.Collections.Generic;
using System.Security.Policy;
using Gameplay.PVE.Utils;
using ImageEffects;
using UnityEngine;
using UnityEngine.AI;
using Yoozoo.Framework.Core;
using Yoozoo.Gta.Common;

namespace Gameplay.PVE.Survivor
{
    
    public class DeckManager: BattleSingleton<DeckManager>
    {
        private class DeckCell
        {
            public BattleGameObject circleObject;
            public Animation animation;
            public DeckCircleController controller;
            public GameObject touchObject;
            public Vector3 position;

            public DeckTouchTag tag;
            public int heroId = -1;
            public int heroRare = 4;
            public BattleGameObject heroModel;
            public bool active;
        }
        
        private DeckTouchManager deckTouchManager;
        private List<Vector3> heroPositions = new List<Vector3>();
        
        private List<DeckCell> deckCells = new List<DeckCell>();
        

        private int touchHeroId = -1;
        private int touchHeroIndex = -1;
        private int dragTargetIndex = -1;

        private bool isInDeck;

        public bool IsInDeck => isInDeck;


        private Vector3 center;
        private Vector3 forward;

        private Quaternion rotation;

        public Vector3 Center => center;
        public Vector3 Forward => forward;

        private BattleGameObject torch;
        
        public void PrepareScene(Vector3 center,Vector3 forward)
        {
            this.center = center;
            this.forward = forward;
            rotation = Quaternion.FromToRotation(Vector3.forward, forward);
            var angle = PveUtils.GetAngle(Vector3.forward, forward);
            isInDeck = true;
            if (deckTouchManager == null)
            {
                deckTouchManager = new DeckTouchManager();
            }
            deckTouchManager.Initialize();
            heroPositions = BattleConstValue.GetDeckHeroPositions();
            deckCells.Clear();
            for (int i = 0; i < heroPositions.Count; i++)
            {
                var cell = new DeckCell();
                var position = rotation * heroPositions[i] + center;
                
                var circleObject = BattlePoolManager.Instance.Get(EBattleResId.DeckCircle);
                circleObject.Position = position + new Vector3(0,0.1f,0);
                circleObject.Scale = new Vector3(1.3f, 1.3f, 1.3f);
                circleObject.Parent = SurvivorManager.Instance.Root;
                circleObject.SetPrefabReadyAction((o) =>
                {
                    cell.controller = o.GetComponentInChildren<DeckCircleController>();
                    cell.animation = cell.controller.animation;
                    cell.animation.Stop();
                    cell.animation.Play("ani_sfx_buzheng_resid");
                    o.transform.localEulerAngles = new Vector3(90, angle, 0);
                });
                
                cell.circleObject = circleObject;
                var touchObject = new GameObject("DeckTouch_" + i);
                touchObject.transform.position = position;
                touchObject.transform.parent = SurvivorManager.Instance.Root;
                var boxCollider = touchObject.AddComponent<BoxCollider>();
                boxCollider.size = new Vector3(1.2f,2,1.2f);
                boxCollider.center = new Vector3(0, 0.8f, 0);
                touchObject.AddComponent<DeckTouchTag>().heroIndex = i;
                touchObject.layer = BattleConstValue.SurvivorDeckLayer;
                cell.touchObject = touchObject;
                cell.position = position;
                //主角隐藏
                if (i == 0)
                {
                    boxCollider.enabled = false;
                    cell.active = false;
                    //cell.circleObject.Active = false;
                }
                else
                {
                    cell.active = true;
                }
                deckCells.Add(cell);
            }

            touchHeroId = -1;
            touchHeroIndex = -1;
            dragTargetIndex = -1;
            
            //SetIsNight(StageManager.Instance.isNight);
        }

        public void DoClick(int positionIndex)
        {
            if (!HasHero(positionIndex))
            {
                return;
            }
            var heroId = deckCells[positionIndex].heroId;
            ResidentHandler.Inst.GetFunction("L_SurvivorManager.RemoveDeckHero").Action(heroId);
        }
        
        public void DoDragStart(int positionIndex)
        {
            if (!HasHero(positionIndex))
            {
                return;
            }
            touchHeroIndex = positionIndex;
        }

        public void DoDrag(Vector3 offset)
        {
            if (touchHeroIndex == -1)
            {
                return;
            }
            var index = touchHeroIndex;
            var cell = deckCells[index];
            var touchObject = cell.touchObject;
            var position = offset + cell.position;
            touchObject.transform.position = position;

            var closestIndex = GetClosestIndex(position);
            for (int i = 0; i < deckCells.Count; i++)
            {
                if (i == touchHeroIndex)
                {
                    //是否跟别人换过位置
                    if (closestIndex != i)
                    {
                        SetCircleColor(touchHeroIndex,HasHero(closestIndex));
                    }
                    else
                    {
                        SetCircleColor(touchHeroIndex,true);
                    }
                }
                else if (i == closestIndex)
                {
                    //交换模型位置
                    deckCells[i].touchObject.transform.position = cell.position;
                    if (dragTargetIndex != closestIndex)
                    {
                        SetCircleColor(closestIndex,true);
                        var rare = deckCells[touchHeroIndex].heroRare;
                        var changeName = BattleConstValue.GetDeckCircleAnimationChange(rare);
                        PlayCircleAnimation(closestIndex,changeName);
                    }
                }
                else
                {
                    deckCells[i].touchObject.transform.position = deckCells[i].position;
                    RefreshCircleColor(i);
                }
            }
            dragTargetIndex = closestIndex;
        }

        public void DoDragEnd()
        {
            if (touchHeroIndex < 0 || dragTargetIndex < 0)
            {
                return;
            }

            for (int i = 0; i < deckCells.Count; i++)
            {
                var touchObject = deckCells[i].touchObject;
                touchObject.transform.position = deckCells[i].position;
            }

            if (dragTargetIndex == touchHeroIndex)
            {
                
            }
            else
            {
                //交换模型
                SwitchModel(dragTargetIndex,touchHeroIndex);
                //更新数据
                (deckCells[dragTargetIndex].heroId, deckCells[touchHeroIndex].heroId) = (deckCells[touchHeroIndex].heroId, deckCells[dragTargetIndex].heroId);
                (deckCells[dragTargetIndex].heroModel, deckCells[touchHeroIndex].heroModel) = (deckCells[touchHeroIndex].heroModel, deckCells[dragTargetIndex].heroModel);
                (deckCells[dragTargetIndex].heroRare, deckCells[touchHeroIndex].heroRare) = (deckCells[touchHeroIndex].heroRare, deckCells[dragTargetIndex].heroRare);
                //通知UI
                ResidentHandler.Inst.GetFunction("L_SurvivorManager.SwitchDeckHero").Action(dragTargetIndex,touchHeroIndex);
            }
            
            for (int i = 0; i < deckCells.Count; i++)
            {
                SetCircleColor(i,HasHero(i));
            }

            var rare = deckCells[dragTargetIndex].heroRare;
            var name = BattleConstValue.GetDeckCircleAnimationDown(rare);
            PlayCircleAnimation(dragTargetIndex,name);
            
            touchHeroId = -1;
            touchHeroIndex = -1;
            dragTargetIndex = -1;
        }

        private void SwitchModel(int index1, int index2)
        {
            ResetModelParent(index1,index2);
            ResetModelParent(index2,index1);
        }

        private void ResetModelParent(int fromIndex, int targetIndex)
        {
            var parent = deckCells[targetIndex].touchObject.transform;
            if (deckCells[fromIndex].heroModel != null)
            {
                deckCells[fromIndex].heroModel.Parent = parent;
                deckCells[fromIndex].heroModel.LocalPosition = new Vector3(0, 0, 0);
            }
        }

        private int GetClosestIndex(Vector3 position)
        {
            var distance = 9999f;
            var index = -1;
            for (int i = 0; i < deckCells.Count; i++)
            {
                var cell = deckCells[i];
                if (!cell.active)
                {
                    continue;
                }
                var d = Vector3.Distance(position, cell.position);
                if (d < distance)
                {
                    distance = d;
                    index = i;
                }
            }
            return index;
        }
        
        public override void Update()
        {
            deckTouchManager?.Update();
        }

        private void SetCircleColor(int index, bool hasHero = false)
        {
            var circle = deckCells[index];
            var animation = circle.animation;
            if (animation)
            {
                animation.Stop();
                if (hasHero)
                {
                    var rare = deckCells[index].heroRare;
                    var name = BattleConstValue.GetDeckCircleAnimationResId(rare);
                    animation.Play(name);
                }
                else
                {
                    animation.Play("ani_sfx_buzheng_resid");
                }
                animation.Sample();
                circle.controller.SetHeroState(hasHero);
            }
        }

        private bool HasHero(int heroIndex)
        {
            return deckCells[heroIndex].heroId > 0;
        }

        public void PlayCircleAnimation(int index, string name)
        {
            for (int i = 0; i < deckCells.Count; i++)
            {
                var cell = deckCells[i];
                if (i == index)
                {
                    cell.animation.Stop();
                    cell.animation.Play(name);
                }
            }
        }

        private void RefreshCircleColor(int index)
        {
            var hasHero = HasHero(index);
            SetCircleColor(index,hasHero);
        }

        public int SetHero(int index, int heroId,int heroRare,bool showEffect = true)
        {
            if (index == -1)//选择一个位置
            {
                for (int i = 0; i < deckCells.Count; i++)
                {
                    if (!HasHero(i))
                    {
                        index = i;
                        break;
                    }
                }
            }
            if (index == -1)//没找到位置
            {
                return index;
            }
            
            //设置数据
            deckCells[index].heroId = heroId;
            deckCells[index].heroRare = heroRare;
            RefreshCircleColor(index);
            if (showEffect)
            {
                var rare = deckCells[index].heroRare;
                var placeName = BattleConstValue.GetDeckCircleAnimationPlace(rare);
                PlayCircleAnimation(index,placeName);
            }
            
            var touchObject = deckCells[index].touchObject;
            var touchObjectTransform = touchObject.transform;
            
            //加载模型
            var heroConfig = BattleConfigManager.Instance.GetHeroConfig(heroId);
            var heroObject = BattlePoolManager.Instance.Get(heroConfig.res_id,OnHeroModelReady);
            deckCells[index].heroModel = heroObject;
            heroObject.Parent = touchObjectTransform;
            heroObject.LocalPosition = new Vector3(0, 0, 0);
            heroObject.Forward = forward;
            return index;
        }
        
        private void OnHeroModelReady(GameObject gameObject)
        {
            var animator = gameObject.GetComponent<Animator>();
            animator.SetTrigger("Idle");
            animator.SetFloat("Speed",0);
            var lightElement = gameObject.GetComponent<SurvivorLightElement>();
            if(lightElement != null)
            {
                lightElement.controllerMark = BattleConstValue.LightElementMark;
                lightElement.Refresh();
            }
        }

        public void RemoveHeroByHeroId(int heroId)
        {
            for (int i = 0; i < deckCells.Count; i++)
            {
                if (deckCells[i].heroId == heroId)
                {
                    RemoveHero(i);
                    break;
                }
            }
        }

        private void RemoveHero(int index)
        {
            if (deckCells[index].heroModel != null)
            {
                BattlePoolManager.Instance.Release(deckCells[index].heroModel);
                deckCells[index].heroModel = null;
            }
            deckCells[index].heroId = -1;
            RefreshCircleColor(index);
            PlayCircleAnimation(index,"ani_sfx_buzheng_resid");
        }

        public void DeckToBattle()
        {
            SurvivorDataManager.Instance.Clear();
            for (int i = 0; i < deckCells.Count; i++)
            {
                if (deckCells[i].heroId > 0)
                {
                    SurvivorDataManager.Instance.AddHero(i,deckCells[i].heroId);
                }
            }
            StageManager.Instance.StartBattle();
            isInDeck = false;
        }
        
        public List<Vector2Int> GetDeckHeroIds()
        {
            var heroIds = new List<Vector2Int>();
            for (int i = 0; i < deckCells.Count; i++)
            {
                if (deckCells[i].heroId > 0)
                {
                    heroIds.Add(new Vector2Int(i,deckCells[i].heroId));
                }
            }
            return heroIds;
        }

        public Vector3 GetDeckPosition(int index)
        {
            if (deckCells.Count > index)
            {
                return deckCells[index].position;
            }
            return BattleConstValue.DEFAULT_POINT;
        }

        public void ClearBase()
        {
            for (int i = 0; i < deckCells.Count; i++)
            {
                if (deckCells[i].heroModel != null)
                {
                    BattlePoolManager.Instance.Release(deckCells[i].heroModel);
                    deckCells[i].heroModel = null;
                }
                if (deckCells[i].circleObject != null)
                {
                    BattlePoolManager.Instance.Release(deckCells[i].circleObject);
                    deckCells[i].circleObject = null;
                }

                if (deckCells[i].touchObject != null)
                {
                    GameObject.DestroyImmediate(deckCells[i].touchObject);
                    deckCells[i].touchObject = null;
                }
            }
            deckCells.Clear();
            HideTorch();
        }

        public void OnMapReady()
        {
            //重新设置高度
            for (int i = 0; i < deckCells.Count; i++)
            {
                var cell = deckCells[i];
                var position = cell.position;
                if (NavMesh.SamplePosition(position,out var hit,10,NavMesh.AllAreas))
                {
                    cell.position = hit.position;
                    cell.touchObject.transform.position = hit.position;
                    cell.circleObject.Position = hit.position + new Vector3(0,0.1f,0);
                    if (torch != null)
                    {
                        torch.Position = hit.position;
                    }
                }
            }
        }

        public void SetIsNight(bool isNight)
        {
            if (isNight)
            {
                ShowTorch();
            }
            else
            {
                HideTorch();
            }
        }

        private void ShowTorch()
        {
            if (torch == null)
            {
                torch = BattlePoolManager.Instance.Get(EBattleResId.Torch);
                torch.Position = center;
                torch.Forward = forward;
            }
        }

        private void HideTorch()
        {
            if (torch != null)
            {
                BattlePoolManager.Instance.Release(torch);
                torch = null;
            }
        }
        
        public override void Dispose()
        {
            ClearBase();
        }
    }
}
